home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
os20
/
cdity
/
yak14a.lha
/
Yak
/
Source
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-22
|
16KB
|
714 lines
/*
* Yak version 1.3f
* ----------------
* [Yak == Yet Another K(?)ommodity
*
* There seems to be a profusion of commodities doing this or that.
* Heres mine, to do what I want it to:
*
* AutoActivate windows (SunMouse)
* ClickToFront, ClickToBack, ScreenCycle
* Close/Zip/Shrink/Zoom/Turn a window via keyboard.
* Bring up a palette on front screen.
* Insert date into read-stream.
* Produce key-click (like my keyclick program).
* Some other things...
*
* Martin W. Scott, 9/92.
*/
#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <graphics/displayinfo.h>
#include <libraries/commodities.h>
#include <libraries/reqtools.h>
#include <libraries/locale.h>
#include <intuition/intuitionbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/commodities.h>
#include <proto/intuition.h>
#include <proto/reqtools.h>
#include <proto/locale.h>
#include <string.h>
#include "yak.h"
#include "beep.h"
#include "icon.h"
#include "version.h"
#include "WB2CLI.h" /* we'll be a shell process */
#define DEF_CURRENTDIR "SYS:"
/* local prototypes for main.c */
static void CloseResources(void);
static BOOL OpenResources(void);
static void __regargs EasyEasyRequest(char *str);
static void FreePatterns(void);
static void DoCloseWindow(void);
static void __regargs HandleWindowKey(LONG what);
static void InsertDate(void);
static void DoCycleWindows(void);
static void DoCycleScreens(void);
static void DoCenterScreen(void);
static struct Window *FindWBWindow(void);
static LONG ProcessMsg(void);
static void __saveds DoPalette(void);
void __saveds __asm putcharfunc(register __a0 struct Hook * h,
register __a2 void * object,
register __a1 char c);
void __main(void);
#ifdef __SASC_60 /* save some bytes */
void _MemCleanup(void){}
#else
void MemCleanup(void){}
#endif
/* global data - library bases and the like */
extern struct WBStartup *_WBenchMsg;
struct Library *CxBase, *IconBase,
*GadToolsBase, *LayersBase,
*WorkbenchBase, *LocaleBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Locale *locale;
struct MsgPort *broker_mp;
CxObj *broker;
char *versionstr="\0$VER: "VERSION_NAME;
struct NewBroker newbroker = {
NB_VERSION,
"Yak", /* string to identify this broker */
VERSION_STR,
"Multi-purpose commodity",
NBU_UNIQUE | NBU_NOTIFY, /* Don't want any new commodities
* starting with this name. If someone
* tries it, let me know */
COF_SHOW_HIDE
};
ULONG wndsigflag; /* here for overlay purposes */
ULONG cxsigflag;
ULONG invariantsigflag;
BYTE palette_count; /* how many palettes are open */
/* from handler.c */
extern ULONG clicksigflag, intuiopsigflag;
extern void (*intui_routine)(APTR); /* for intui_op's */
extern APTR intui_parameter;
/* from icon.c */
extern ULONG appsigflag;
/* close what we opened */
static void
CloseResources()
{
if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
if (GfxBase) CloseLibrary((struct Library *)GfxBase);
if (CxBase) CloseLibrary(CxBase);
if (LayersBase) CloseLibrary(LayersBase);
if (IconBase) CloseLibrary(IconBase);
if (GadToolsBase) CloseLibrary(GadToolsBase);
if (WorkbenchBase) CloseLibrary(WorkbenchBase);
if (LocaleBase)
{
CloseLocale(locale);
CloseLibrary(LocaleBase);
}
}
/* open libraries, devices that we need */
static BOOL
OpenResources()
{
if ((IntuitionBase = (void *)OpenLibrary("intuition.library", 37L)) &&
(GfxBase = (void *)OpenLibrary("graphics.library", 37L)) &&
(CxBase = OpenLibrary("commodities.library", 37L)) &&
(LayersBase = OpenLibrary("layers.library", 37L)) &&
(IconBase = OpenLibrary("icon.library", 37L)) &&
(GadToolsBase = OpenLibrary("gadtools.library", 37L)) &&
(WorkbenchBase = OpenLibrary("workbench.library", 37L)))
{
if (LocaleBase = OpenLibrary("locale.library", 38L))
if (!(locale = OpenLocale(NULL)))
{
PostError("No locale set!\n");
CloseLibrary(LocaleBase);
LocaleBase = NULL;
}
return TRUE;
}
CloseResources();
return FALSE;
}
/* pop up a requester */
static void __regargs
EasyEasyRequest(char *str)
{
struct EasyStruct es;
es.es_StructSize = sizeof(struct EasyStruct);
es.es_Flags = 0L;
es.es_Title = "Yak Message";
es.es_TextFormat = str;
es.es_GadgetFormat = "OK";
EasyRequestArgs(NULL, &es, NULL, NULL);
}
/* display an error appropriately */
void __regargs
PostError(char *str)
{
if (IntuitionBase)
EasyEasyRequest(str);
else
{
PutStr("Yak: ");
PutStr(str);
PutStr("\n");
}
}
/* modify hk array with new hotkey */
BOOL __regargs
AddHotKey(char *newstr, UWORD n)
{
CxObj *newfilter;
char *hotkey = newstr ? newstr : hk[n].key;
if (!hotkey[0]) /* hotkey being cancelled */
{
if (hk[n].filter) DeleteCxObjAll(hk[n].filter);
hk[n].filter = NULL;
hk[n].key[0] = '\0';
return TRUE;
}
else if (newfilter = HotKey(hotkey, broker_mp, hk[n].msgid))
{
if (hk[n].filter) DeleteCxObjAll(hk[n].filter);
hk[n].filter = newfilter;
if (newstr) strncpy(hk[n].key, newstr, MAXKEYLEN);
AttachCxObj(broker, hk[n].filter);
return TRUE;
}
PostError("Invalid hotkey definition");
return FALSE;
}
/* parse pattern, report errors */
BOOL __regargs
InitPattern(char *newpatstr, UWORD n)
{
char *patstr = newpatstr ? newpatstr : patterns[n].patstr;
char *pat;
LONG len;
if (pat = AllocVec(len = strlen(patstr)*3+10, MEMF_CLEAR))
{
if (ParsePattern(patstr, pat, len) != -1)
{
if (newpatstr) strncpy(patterns[n].patstr, newpatstr, PATLEN);
if (patterns[n].pat) FreeVec(patterns[n].pat);
patterns[n].pat = pat;
return TRUE;
}
PostError("Pattern parse error");
FreeVec(pat);
}
else PostError("Allocation error");
return FALSE;
}
static void
FreePatterns()
{
UWORD i;
for (i = 0; i < NUM_PATTERNS; i++)
if (patterns[i].pat) FreeVec(patterns[i].pat);
}
void
__main() /* Yak: multi-function commodity */
{
BPTR newdir = NULL, olddir;
if (OpenResources())
{
if (broker_mp = CreateMsgPort())
{
newbroker.nb_Port = broker_mp;
cxsigflag = 1L << broker_mp->mp_SigBit;
/* process tool-types */
GetOurIcon(_WBenchMsg);
newbroker.nb_Pri = (BYTE)TTInt("CX_PRIORITY", 0);
if (_WBenchMsg)
{
if (newdir = Lock(DEF_CURRENTDIR, ACCESS_READ))
olddir = CurrentDir(newdir);
WB2CLI(_WBenchMsg,4000,DOSBase); /* get it over with... */
}
if (broker = CxBroker(&newbroker, NULL))
{
/* HANDLER FIRST, SO IT SEES EVERYTHING!!! */
if (InitHandler())
{
LoadSettings(CONFIG_FILE);
/* tooltype overrides config file */
AddHotKey(TTString("CX_POPKEY", NULL), HK_POPKEY);
MyPri(ACTIVE);
ActivateCxObj(broker, 1L);
if (TTBool("CX_POPUP", FALSE))
ShowWindow();
if (!TTBool("NOICON", FALSE))
{
if (!MakeOurAppIcon(TTString("ICONNAME", "Yak!")))
if (_WBenchMsg)
PostError("Couldn't create icon");
}
/* WB makes a copy of icon, so can free it */
FreeOurIcon();
/* these are the signals waited for, + window sig */
invariantsigflag = SIGBREAKF_CTRL_C | cxsigflag
| clicksigflag | intuiopsigflag
| appsigflag;
while (ProcessMsg())
;
HideWindow();
RemoveOurAppIcon();
MyPri(ORIGINAL);
EndHandler();
FreePatterns();
}
else PostError("Allocation error");
DeleteCxObjAll(broker);
}
if (newdir) {
CurrentDir(olddir);
UnLock(newdir);
}
DeleteMsgPort(broker_mp);
FreeOurIcon(); /* may already be gone, but so what? */
}
else PostError("Allocation error");
CloseResources();
}
else PostError("Resource error");
}
/* simulate user clicking close-gadget */
static void
DoCloseWindow()
{
struct InputEvent ev;
struct Window *window;
ULONG lock;
lock = LockIBase(0);
window = IntuitionBase->ActiveWindow;
UnlockIBase(lock);
if (window && (window->IDCMPFlags & CLOSEWINDOW))
{
ev.ie_NextEvent = NULL;
ev.ie_Class = IECLASS_CLOSEWINDOW;
ev.ie_SubClass = 0;
ev.ie_Code = 0;
ev.ie_Qualifier = 0;
ev.ie_EventAddress = 0;
AddIEvents(&ev);
}
}
#define AdjustedLeftEdge(w, width) (w->LeftEdge + width > w->WScreen->Width ? \
w->WScreen->Width - width : w->LeftEdge)
#define AdjustedTopEdge(w, height) (w->TopEdge + height > w->WScreen->Height ? \
w->WScreen->Height - height : w->TopEdge)
/* zip/enlarge or whatever the currently active window */
static void __regargs
HandleWindowKey(LONG what)
{
struct Window *window;
ULONG lock;
lock = LockIBase(0);
if (window = IntuitionBase->ActiveWindow)
{
switch (what)
{
case HK_ZIPKEY:
if (window->Flags & WFLG_HASZOOM)
ZipWindow(window);
break;
case HK_SHRINKKEY:
if (window->Flags & WFLG_SIZEGADGET)
ChangeWindowBox(window,
window->LeftEdge,
window->TopEdge,
window->MinWidth,
window->MinHeight);
break;
case HK_ZOOMKEY:
{ /* sometimes Max vars are -1 == NO LIMIT */
USHORT width, height;
width = window->MaxWidth;
if (width == -1) width = window->WScreen->Width-width;
height = window->MaxHeight;
if (height == -1) height = window->WScreen->Height-height;
if (window->Flags & WFLG_SIZEGADGET)
ChangeWindowBox(window,
AdjustedLeftEdge(window, width),
AdjustedTopEdge(window, height),
width,
height);
}
break;
} /* switch */
}
UnlockIBase(lock);
}
/* bring a palette up on frontmost screen */
/* CreateNewProc it... */
static void __saveds
DoPalette()
{
struct ReqToolsBase *ReqToolsBase;
LONG tags[3];
palette_count++;
if (ReqToolsBase = (void *)OpenLibrary("reqtools.library", 0L))
{
tags[0] = RT_Screen;
tags[1] = (LONG)ReqToolsBase->IntuitionBase->FirstScreen;
tags[2] = TAG_DONE;
(void) rtPaletteRequestA("Palette", NULL, (struct TagItem *)tags);
CloseLibrary(ReqToolsBase);
}
palette_count--;
}
/* hook-function for inserting chars into input-stream */
void __saveds __asm
putcharfunc( register __a0 struct Hook *h,
register __a2 void *object,
register __a1 char c)
{
struct InputEvent ev;
if (c) /* stop at null-terminator */
{
ev.ie_NextEvent = NULL;
InvertKeyMap(c, &ev, NULL);
AddIEvents(&ev);
ev.ie_Code |= IECODE_UP_PREFIX;
AddIEvents(&ev);
}
}
/* and its associated structure */
struct Hook putcharhook = {
{NULL, NULL},
(APTR)putcharfunc,
NULL,
NULL
};
/* if locale present, insert date as string into read-stream */
static void
InsertDate()
{
struct DateStamp datestamp;
DateStamp(&datestamp);
if (LocaleBase)
FormatDate(locale, DateFormat, &datestamp, &putcharhook);
else
DisplayBeep(NULL);
}
/* cyle windows, like IHelp */
/*#define NOCYCLEFLAGS (WFLG_WBENCHWINDOW|WFLG_BACKDROP)*/
#define NOCYCLEFLAGS (WFLG_BACKDROP)
static void
DoCycleWindows()
{
struct Screen *s;
struct Window *w, *backmost;
struct Layer *l;
ULONG lock;
lock = LockIBase(0);
if (s = IntuitionBase->FirstScreen)
{
Forbid();
backmost = NULL;
for (l = s->LayerInfo.top_layer; l; l = l->back)
{
w = (struct Window *)l->Window;
if (w && !(w->Flags & NOCYCLEFLAGS))
backmost = w;
}
if (backmost)
{
ScreenToFront(s);
WindowToFront(backmost);
ActivateWindow(backmost);
}
Permit();
}
UnlockIBase(lock);
}
/* cyle screens, like IHelp */
static void
DoCycleScreens()
{
struct Screen *s;
ULONG lock;
lock = LockIBase(0);
for (s = IntuitionBase->FirstScreen; s; s = s->NextScreen)
if (!s->NextScreen)
{
ScreenToFront(s);
if (scractivate)
ActivateMouseWindow(SCREEN);
break;
}
UnlockIBase(lock);
}
/* center horizontally the frontmost screen */
static void
DoCenterScreen()
{
struct Rectangle rect;
struct Screen *s;
ULONG lock;
ULONG modeid;
WORD newle;
lock = LockIBase(0);
if ((s = IntuitionBase->FirstScreen) &&
(modeid = GetVPModeID(&s->ViewPort)) != INVALID_ID &&
QueryOverscan(modeid, &rect, OSCAN_TEXT))
{
newle = (rect.MinX + rect.MaxX + 1 - s->Width) >> 1;
MoveScreen(s, newle - s->LeftEdge, 0);
}
UnlockIBase(lock);
}
/* find (a) Workbench window; used below, AND in handler.c */
static struct Window *
FindWBWindow()
{
struct Screen *s = LockPubScreen("Workbench");
if (s)
{
struct Window *w = s->FirstWindow;
WBenchToFront();
Forbid();
for (; w; w = w->NextWindow)
if (w->Flags & WFLG_WBENCHWINDOW)
break;
Permit();
UnlockPubScreen(NULL, s);
return w;
}
return NULL;
}
/* taglist for CreateNewProc */
LONG palette_taglist[] = {
NP_Entry, (LONG)DoPalette,
NP_Name, (LONG)"Yak Palette",
TAG_DONE
};
/* monitor cx port, act on messages */
static LONG
ProcessMsg(void)
{
CxMsg *msg;
ULONG sigrcvd, msgid, msgtype;
LONG returnvalue = 1L;
sigrcvd = Wait(invariantsigflag | wndsigflag);
if ((sigrcvd & clicksigflag) && click_volume) /* keyclick please */
{
beep(click_volume);
Delay(1); /* avoid ugly sound when key repeating */
}
if (sigrcvd & intuiopsigflag) /* intuiop requested */
intui_routine(intui_parameter);
if (sigrcvd & appsigflag) /* settings change */
{
RespondToAppIcon();
ShowWindow();
}
if (sigrcvd & wndsigflag) /* settings change */
if (HandleIDCMP() != HELP_OKAY)
returnvalue = 0;
else if (!wndsigflag) /* window gone */
DummyOverlay(); /* remove code */
while(msg = (CxMsg *)GetMsg(broker_mp))
{
msgid = CxMsgID(msg);
msgtype = CxMsgType(msg);
ReplyMsg((struct Message *)msg);
switch(msgtype)
{
case CXM_IEVENT:
switch(msgid)
{
case HK_POPKEY:
ShowWindow(); /* check error return? */
break;
case HK_CLOSEKEY:
DoCloseWindow();
break;
case HK_ZIPKEY:
case HK_SHRINKKEY:
case HK_ZOOMKEY:
HandleWindowKey(msgid);
break;
case HK_WORKBENCH:
{
struct Window *w;
if (w = FindWBWindow())
{
WBenchToFront();
ActivateWindow(w);
}
}
break;
case HK_POPPALKEY:
CreateNewProc((struct TagItem *)palette_taglist);
break;
case HK_POPCLI:
{
struct Screen *s;
if (s = LockPubScreen(NULL))
{
ScreenToFront(s);
UnlockPubScreen(NULL, s);
}
MyPri(ORIGINAL);
SystemTagList(PopCommand, NULL);
MyPri(ACTIVE);
}
break;
case HK_INSDATE:
InsertDate();
break;
case HK_CYCLEWIN:
DoCycleWindows();
break;
case HK_CYCLESCR:
DoCycleScreens();
break;
case HK_CENTERSCR:
DoCenterScreen();
break;
case HK_SCRTOBACK: /* replacement for lcommand m */
MyScreenToBack(IntuitionBase->FirstScreen);
break;
case HK_BLANK:
BlankScreen();
break;
}
break;
case CXM_COMMAND:
switch(msgid)
{
case CXCMD_UNIQUE:
case CXCMD_APPEAR:
ShowWindow(); /* check error return? */
break;
case CXCMD_DISAPPEAR:
HideWindow();
DummyOverlay();
break;
case CXCMD_DISABLE:
ActivateCxObj(broker, 0L);
break;
case CXCMD_ENABLE:
ActivateCxObj(broker, 1L);
break;
case CXCMD_KILL:
returnvalue = 0L;
break;
}
break;
}
}
if (sigrcvd & SIGBREAKF_CTRL_C)
returnvalue = 0L;
if (!returnvalue && palette_count)
{
PostError("Cannot exit yet:\npalette(s) remain open");
returnvalue = 1;
}
return(returnvalue);
}